1 module hip.gui.screen;
2 public import hip.gui.widget;
3 import hip.api.input.button;
4 import std.internal.digest.sha_SSSE3;
5 
6 /** 
7  * Screen is where all widgets should be contained.
8  * This way, the event methods are forwarded correctly, there can exist a drag and drop.
9  * Render order by stack is also possible
10  */
11 class Screen : Widget
12 {
13     protected Widget focusedWidget;
14     protected Widget draggedWidget;
15     private Widget widgetHolded;
16     private Widget widgetMouseEntered;
17 
18 
19     this(){setupEvents();}
20 
21     private const(HipButton)* mouseDownEv, mouseUpEv;
22     private const(ScrollListener)* scrollEv;
23     private const(TouchMoveListener)* moveEv;
24 
25 
26 
27     final void setupEvents()
28     {
29         import hip.api:HipInput, HipMouseButton;
30         mouseDownEv = HipInput.addTouchListener(HipMouseButton.left, 
31         (const AHipButtonMetadata meta)
32         {
33             handleMouseDown();
34         });
35 
36         mouseUpEv = HipInput.addTouchListener(HipMouseButton.left,
37         (const(AHipButtonMetadata) meta)
38         {
39             stopDragging();
40             handleMouseUp();
41         }, HipButtonType.up);
42 
43         moveEv = HipInput.addTouchMoveListener((int x, int y)
44         {
45             handleMouseEnter(x, y);
46             startDragging(x, y);
47         });
48         
49         scrollEv = HipInput.addScrollListener((float[3] scroll)
50         {
51             handleScroll(scroll);
52         });
53     }
54     
55 
56     int findWidget(Widget w)
57     {
58         for(int i = 0; i < children.length; i++) 
59             if(children[i] is w) return i;
60         return -1;
61     }
62 
63     private void handleMouseDown()
64     {
65         import hip.api;
66 
67         Widget w = findWidgetAt(HipInput.getWorldTouchPosition());
68         widgetHolded = w;
69         setFocusOn(w);
70         if(w !is null) w.onMouseDown();
71     }
72     private void handleMouseUp()
73     {
74         import hip.api;
75         if(widgetHolded !is null)
76         {
77             widgetHolded.onMouseUp();
78             if(findWidgetAt(HipInput.getWorldTouchPosition()) is widgetHolded)
79                 widgetHolded.onMouseClick();
80         }
81         widgetHolded = null;
82     }
83     private void handleScroll(float[3] scroll)
84     {
85         import hip.api;
86         Widget w = findWidgetAt(HipInput.getWorldTouchPosition());
87         setFocusOn(w);
88         if(w !is null)
89         {
90             import hip.gui.scroll_area;
91             IRawScrollable scrollable = cast(IRawScrollable)w;
92             if(scrollable !is null) scrollable.onRawScroll(scroll);
93         }
94     }
95 
96     private void handleMouseEnter(int x, int y)
97     {
98         Widget mEnterWidget = findWidgetAt(x, y);
99         if(widgetMouseEntered !is mEnterWidget)
100         {
101             if(widgetMouseEntered)
102                 widgetMouseEntered.onMouseExit();
103             if(mEnterWidget)
104                 mEnterWidget.onMouseEnter();
105         }
106         widgetMouseEntered = mEnterWidget;
107     }
108     private void startDragging(int x, int y)
109     {
110         if(widgetHolded && !draggedWidget)
111         {
112             setDragging(widgetHolded, x , y);
113         }
114         if(draggedWidget !is null)
115             draggedWidget.onDragged(x, y);
116     }
117 
118     private void pushToTop(Widget w)
119     {
120         int pos = findWidget(w);
121         if(pos == children.length-1) return;
122         else if(pos != -1)
123         {
124             import hip.api;
125             import hip.util.algorithm;
126             children[pos+1..$].copyInto(children[pos..$-1]);
127             children[$-1] = w;
128         }
129     }
130 
131     void setFocusOn(Widget w)
132     {
133         if(focusedWidget is w) return;
134         if(focusedWidget !is null)
135             focusedWidget.onFocusExit();
136         focusedWidget = w;
137         if(w !is null)
138         {
139             pushToTop(w);
140             w.onFocusEnter();
141         }
142     }
143 
144     void setDragging(Widget w, int x, int y)
145     {
146         if(w !is null && w.isDraggable)
147         {
148             w.onDragStart(x, y);
149             draggedWidget = w;
150         }
151     }
152 
153     void stopDragging()
154     {
155         if(draggedWidget !is null)
156         {
157             draggedWidget.onDragEnd();
158             draggedWidget = null;
159         }
160     }
161 
162 }